package com.thiswhyme.republish.rabbitmq.core;

import cn.hutool.json.JSONUtil;
import com.thiswhyme.republish.common.UidGenService;
import com.thiswhyme.republish.rabbitmq.core.domain.MessageInfo;
import com.thiswhyme.republish.rabbitmq.core.domain.MessageType;
import com.thiswhyme.republish.rabbitmq.core.domain.PublishStatus;
import com.thiswhyme.republish.rabbitmq.datasource.MessageInfoRepo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.CollectionUtils;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * 消息对象维护服务
 * Created by thiswhyme on 2021-03-21.
 */
public class MessageInfoService implements IMessageInfoService {

    public static final Logger log = LoggerFactory.getLogger(MessageInfoService.class);

    private UidGenService uidGenService;
    private MessageInfoRepo messageInfoRepo;

    public MessageInfoService(MessageInfoRepo messageInfoRepo, UidGenService uidGenService) {
        this.messageInfoRepo = messageInfoRepo;
        this.uidGenService = uidGenService;
    }

    @Override
    public List<MessageInfo> listByIds(List<Long> dataIds) {
        if(CollectionUtils.isEmpty(dataIds)) {
            return Collections.EMPTY_LIST;
        }
        return messageInfoRepo.selectByIds(dataIds);
    }

    @Override
    public MessageInfo queryById(Long dataId) {
        List<MessageInfo> msgs = messageInfoRepo.selectByIds(Arrays.asList(dataId));
        if(!CollectionUtils.isEmpty(msgs)) {
            return msgs.get(0);
        }
        return null;
    }

    /**
     * 记录消息
     * @param channelName
     * @param contentClassType
     * @param msgHeaders
     * @param payload
     * @param publishStatus
     * @param type
     * @return
     */
    protected MessageInfo recordMessage(Long dataId, String channelName, String contentClassType,
                                        MessageHeaders msgHeaders, Object payload, PublishStatus publishStatus,
                                        MessageType type) {
        if(null != dataId) {
            MessageInfo info = queryById(dataId);
            if(null != info) {
                log.info("消息已存在，直接返回，id：{}", dataId);
                return info;
            }
        }
        dataId = Optional.ofNullable(dataId).orElseGet(() -> uidGenService.fetchUid());
//      //部分序列化方式序列化AmqpHeaders.CHANNEL会报错（例如Gson），此处可以剔除
//        Map<String, Object> headers = new HashMap<>();
//        msgHeaders.forEach((k, v) -> {
//            if (AmqpHeaders.CHANNEL.equals(k)) {
//                return;
//            }
//            headers.put(k, v);
//        });

        String header = JSONUtil.toJsonStr(msgHeaders);
        String content =  JSONUtil.toJsonStr(payload);
        MessageInfo messageInfo = new MessageInfo()
                .setId(dataId)
                .setType(type.getValue())
                .setChannelName(channelName)
                .setMsgId(msgHeaders.getId().toString())
                .setHeaders(header)
                .setContent(content)
                .setContentClassType(contentClassType)
                .setRetryTimes(0)
                .setPublishStatus(publishStatus.getValue())
                .setCreateTime(Timestamp.from(Instant.now()));
        messageInfoRepo.insert(messageInfo);
        return messageInfo;
    }

    /**
     * 更新重试次数
     * @param dataId
     * @param retryTimes
     * @return
     */
    protected void updateRetryTimes(Long dataId, int retryTimes) {
        int result = messageInfoRepo.updateRetryTimes(dataId, retryTimes);
        if (log.isDebugEnabled()) {
            log.debug("更新【{}】重试次数，结果：{}", dataId, result);
        }
    }

    /**
     * 更新发送状态
     * @param dataId
     * @param status
     * @return
     */
    protected void updatePublishStatus(Long dataId, PublishStatus status) {
        int result = messageInfoRepo.updatePublishStatus(dataId, status);
        if (log.isDebugEnabled()) {
            log.debug("更新【{}】发送状态，结果：{}", dataId, result);
        }
    }
}
